package org.dandsoft.blackbox;

import org.dandsoft.blackbox.study.StudyProcess;

import java.util.Collection;

/**
 * @author Vilyuzhanin Denis (Fin)
 */
public interface BlackBox {

    /**
     * Инициализация. Получает все необходимы объекты для работы включая окружение. Вызывается при создании
     * экземпляра в окружении. Когда экземпляр создается и добавляется в окружение, необходимо что бы он получить
     * все что ему нужно для работы.
     *
     * @param environment  Объект окружения. Все взаимодействие с внешним миром осуществляется
     *                     через этот объект. Не может быть null.
     * @param studyProcess Реализация процесса обучения.
     * @throws NullPointerException Если параметр environment равен null
     * @throws BlackBoxException
     */
    public void init(Enviroment environment, StudyProcess studyProcess) throws BlackBoxException;

    /**
     * Когда экземпляр удаляется из контейнера вызывается этот метод, чтобы объект смог освободить все ресурсы которые
     * занимает.
     *
     * @throws BlackBoxException
     */
    public void stop() throws BlackBoxException;

    /**
     * Произвести активацию. Эта операция имеет самый высокий приоритет, и должна выполняться максимально
     * быстро. Процесс активации это преобразование входных сигналов в выходные. В этом методы выполняется
     * один шаг этого процесса.
     *
     * @throws BlackBoxException
     * @throws InterruprBlackBoxException если квант времени выделенный на активацию истек
     */
    public void activate() throws BlackBoxException;

    /**
     * Процесс обучения. Производит обучение. Процесс обучения может быть долгим и ресурсоемким. По этому необходимо
     * контролировать длительность выполнения. Весь код обучения должен начинаться с восстановаления промежуточных данных
     * и иметь блок finally для сохранения промежуточных данных.
     *
     * @throws BlackBoxException
     * @throws InterruprBlackBoxException если квант времени выделенный на обучение истек. Необходимо разместить в
     *                                    блоке finally код для сохранения промежуточных данных.
     */
    public void study() throws BlackBoxException;

    /**
     * Добавить новый вход. Через этот метод окружение оповещает ящик о том что у него добавился вход
     *
     * @param id Идентификатор входа
     * @throws BlackBoxException
     */
    public void addInput(SignalId id) throws BlackBoxException;

    /**
     * Удалить вход. Через этот метод среда оповещает ящик о том что был удален один выход.
     *
     * @param id идентификатор выхода
     * @throws BlackBoxException
     */
    public void removeInput(SignalId id) throws BlackBoxException;

    /**
     * Получить список всех входов о которых знает ящик
     *
     * @return Коллекция идентификатор всех входов
     * @throws BlackBoxException
     */
    public Collection<SignalId> getInputs() throws BlackBoxException;

    /**
     * Оповестить ящик о том что у него есть выход
     *
     * @param id Идентификатор выхода
     * @throws BlackBoxException
     */
    public void addOutput(SignalId id) throws BlackBoxException;

    /**
     * Оповестить ящик о том что  у него удален выход
     *
     * @param id
     * @throws BlackBoxException
     */
    public void removeOutput(SignalId id) throws BlackBoxException;

    /**
     * Получить колллекцию сигналов которые были получены на входы
     * @return Коллекция сигналов которые были получены на входы
     * @throws BlackBoxException
     */
    public Collection<Signal> getInputSignals() throws BlackBoxException;

    /**
     * Установить значение входного сиганал
     *
     * @param signal Значение входного сигнала
     * @throws BlackBoxException
     */
    public void inputSignal(Signal signal) throws BlackBoxException;

    /**
     * Получить все выходы о которых знает ящик
     *
     * @return Коллекция идентификаторов выходов
     * @throws BlackBoxException
     */
    public Collection<SignalId> getOutputs() throws BlackBoxException;

    /**
     * Получить выходной сигнал
     *
     * @param id Идентификатор выходного сигнала
     * @return Значение сигнала
     * @throws BlackBoxException
     */
    public Signal getOutputSignal(SignalId id) throws BlackBoxException;

    /**
     * Получить значения всех выходных сигналов. Коллекция содержит значений всех сигналов. Включая пассивные.
     *
     * @return Коллекция значений выходных сигналов.
     * @throws BlackBoxException
     */
    public Collection<Signal> getOutputSignals() throws BlackBoxException;

    /**
     * Получить значения всех активных выходных сигналов.
     *
     * @return Коллекция содержит значения всех выходных сигналов.
     * @throws BlackBoxException
     */
    public Collection<Signal> getActiveOutputSignals() throws BlackBoxException;


}
